package com.codeplex.tdmg4mc;

import net.minecraft.client.model.ModelBiped;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

public class ItemGear extends ItemArmor
{
	public static final double GRAVITY_ACCEL=0.2;
	public static final double MAX_VELOCITY=2;
	public static final double BOOST_ACCEL_LEVEL=0.2;
	public static final double BOOST_ACCEL_UP=0.1;
	public static final int FLYING_MAX=30;
	public EntityGearHook hookLeft;
	public EntityGearHook hookRight;
	private double flyingMotionY;
	private int flyingCount;
	private double energy;
	private double prevEnergy;
	private boolean energyUpdate;
	private boolean flying;
	
	public ItemGear(ArmorMaterial material, int renderIndex, int armorType)
	{
		super(material, renderIndex, armorType);
		hookLeft=null;
		hookRight=null;
		flyingCount=0;
		flying=false;
		prevEnergy=energy=-1;
		energyUpdate=true;
		setCreativeTab(CreativeTabs.tabCombat);
	}

	@Override
	public String getArmorTexture(ItemStack stack, Entity entity, int slot, String type)
	{
		return "tdmg:textures/models/armor/gear_layer_2.png";
	}

	@Override
	public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack)
	{
		super.onArmorTick(world, player, itemStack);
		if(TDMG.isClient==world.isRemote)
		{
			TDMGKeyInput.update();
			float y=player.rotationYaw/180.0f*(float)Math.PI;
			double c=MathHelper.cos(y)*0.2;
			double s=MathHelper.sin(y)*0.2;
			if(energyUpdate)
			{
				prevEnergy=energy=player.motionX*player.motionX+player.motionY*player.motionY+player.motionZ*player.motionZ+GRAVITY_ACCEL*player.posY;
				energyUpdate=false;
			}
			if(TDMGKeyInput.shoot)
			{
				TDMGKeyInput.shoot=false;
				if(hookLeft==null||hookLeft.isDead)
				{
					Vec3 d=player.getLookVec();
					d.rotateAroundX(10.0f/180.0f*(float)Math.PI);
					d.rotateAroundY(10.0f/180.0f*(float)Math.PI);
					hookLeft=new EntityGearHook(world, player, true, d);
					world.spawnEntityInWorld(hookLeft);
				}
				if(hookRight==null||hookRight.isDead)
				{
					Vec3 d=player.getLookVec();
					d.rotateAroundX(10.0f/180.0f*(float)Math.PI);
					d.rotateAroundY(-10.0f/180.0f*(float)Math.PI);
					hookRight=new EntityGearHook(world, player, false, d);
					world.spawnEntityInWorld(hookRight);
				}
			}
			if(TDMGKeyInput.left&&(hookLeft==null||hookLeft.isDead))
			{
				TDMGKeyInput.left=false;
				hookLeft=new EntityGearHook(world, player, true);
				world.spawnEntityInWorld(hookLeft);
			}
			if(TDMGKeyInput.right&&(hookRight==null||hookRight.isDead))
			{
				TDMGKeyInput.right=false;
				hookRight=new EntityGearHook(world, player, false);
				world.spawnEntityInWorld(hookRight);
			}
			if(TDMGKeyInput.remove)
			{
				TDMGKeyInput.remove=false;
				if(hookLeft!=null) hookLeft.setDead();
				if(hookRight!=null) hookRight.setDead();
			}
			if(TDMGKeyInput.boost)
			{
				TDMGKeyInput.boost=false;
				int ii=-1;
				int md=0;
				for(int i=0;i<player.inventory.mainInventory.length;++i)
				{
					ItemStack it=player.inventory.mainInventory[i];
					if(it!=null&&it.getItem()==TDMG.fuel&&(ii<0||it.getItemDamage()>md))
					{
						ii=i;
						md=it.getItemDamage();
					}
				}
				if(ii>=0)
				{
					flying=true;
					player.inventory.mainInventory[ii].attemptDamageItem(1, itemRand);
					if(player.inventory.mainInventory[ii].getItemDamage()>TDMG.fuel.getMaxDamage()) player.inventory.mainInventory[ii]=null;
					Vec3 l=player.getLookVec();
					double h=Math.sqrt(l.xCoord*l.xCoord+l.zCoord*l.zCoord);
					l.yCoord+=h*0.35;
					double f=BOOST_ACCEL_LEVEL;
					if(l.yCoord>0.0)
					{
						double a=Math.atan2(l.yCoord, h)*2.0/Math.PI;
						f*=1.0-a;
						f+=BOOST_ACCEL_UP*a;
					}
					f/=l.lengthVector();
					player.addVelocity(l.xCoord*f, l.yCoord*f, l.zCoord*f);
			        world.spawnParticle("explode", player.posX+c, player.posY-1, player.posZ+s, 0.0, 0.0, 0.0);
			        world.spawnParticle("explode", player.posX-c, player.posY-1, player.posZ-s, 0.0, 0.0, 0.0);
					energyUpdate=true;
				}
				if(TDMGKeyInput.auto)
				{
					Vec3 m=world.getWorldVec3Pool().getVecFromPool(player.motionX, player.motionY, player.motionZ).normalize();
					if(hookLeft!=null&&!hookLeft.isDead&&hookLeft.isHolding())
					{
						Vec3 a=world.getWorldVec3Pool().getVecFromPool(hookLeft.posX-player.posX, hookLeft.posY-player.posY, hookLeft.posZ-player.posZ).normalize();
						if(Math.acos(m.dotProduct(a))>135.0/180.0*Math.PI) hookLeft.setDead();
					}
					if(hookRight!=null&&!hookRight.isDead&&hookRight.isHolding())
					{
						Vec3 a=world.getWorldVec3Pool().getVecFromPool(hookRight.posX-player.posX, hookRight.posY-player.posY, hookRight.posZ-player.posZ).normalize();
						if(Math.acos(m.dotProduct(a))>135.0/180.0*Math.PI) hookRight.setDead();
					}
					if(hookLeft==null||hookLeft.isDead)
					{
						Vec3 d=player.getLookVec();
						d.rotateAroundX(10.0f/180.0f*(float)Math.PI);
						d.rotateAroundY(10.0f/180.0f*(float)Math.PI);
						Vec3 p=player.getPosition(1.0f).addVector(c, -1, s);
						if(world.rayTraceBlocks(p, p.addVector(d.xCoord*100.0, d.yCoord*100.0, d.zCoord*100.0), false)!=null)
						{
							hookLeft=new EntityGearHook(world, player, true, d);
							world.spawnEntityInWorld(hookLeft);
						}
					}
					if(hookRight==null||hookRight.isDead)
					{
						Vec3 d=player.getLookVec();
						d.rotateAroundX(10.0f/180.0f*(float)Math.PI);
						d.rotateAroundY(-10.0f/180.0f*(float)Math.PI);
						Vec3 p=player.getPosition(1.0f).addVector(-c, -1, -s);
						if(world.rayTraceBlocks(p, p.addVector(d.xCoord*100.0, d.yCoord*100.0, d.zCoord*100.0), false)!=null)
						{
							hookRight=new EntityGearHook(world, player, true, d);
							world.spawnEntityInWorld(hookRight);
						}
					}
				}
			}
			if(hookLeft!=null&&!hookLeft.isDead&&hookLeft.isHolding())
			{
				double d=hookLeft.getDistanceToEntity(player);
				if(d>hookLeft.getLength())
				{
					if(player.posY<hookLeft.posY)
					{
						Vec3 o=world.getWorldVec3Pool().getVecFromPool(player.posX-hookLeft.posX, player.posY-hookLeft.posY, player.posZ-hookLeft.posZ).normalize();
						double l=player.motionX*o.xCoord+player.motionY*o.yCoord+player.motionZ*o.zCoord;
						o.xCoord*=l;
						o.yCoord*=l;
						o.zCoord*=l;
						player.motionX-=o.xCoord;
						player.motionY-=o.yCoord;
						player.motionZ-=o.zCoord;
					}
					double a=(d-hookLeft.getLength())/d;
					double dx=(hookLeft.posX-player.posX)*a;
					double dy=(hookLeft.posY-player.posY)*a;
					double dz=(hookLeft.posZ-player.posZ)*a;
					Vec3 p=world.getWorldVec3Pool().getVecFromPool(player.posX, player.posY, player.posZ);
					Vec3 np=p.addVector(dx, dy, dz);
					if(world.rayTraceBlocks(p, np, false)==null) player.setPosition(np.xCoord, np.yCoord, np.zCoord);
					energyUpdate=true;
				}
			}
			if(hookRight!=null&&!hookRight.isDead&&hookRight.isHolding())
			{
				double d=hookRight.getDistanceToEntity(player);
				if(d>hookRight.getLength())
				{
					if(player.posY<hookRight.posY)
					{
						Vec3 o=world.getWorldVec3Pool().getVecFromPool(player.posX-hookRight.posX, player.posY-hookRight.posY, player.posZ-hookRight.posZ).normalize();
						double l=player.motionX*o.xCoord+player.motionY*o.yCoord+player.motionZ*o.zCoord;
						o.xCoord*=l;
						o.yCoord*=l;
						o.zCoord*=l;
						player.motionX-=o.xCoord;
						player.motionY-=o.yCoord;
						player.motionZ-=o.zCoord;
					}
					double a=(d-hookRight.getLength())/d;
					double dx=(hookRight.posX-player.posX)*a;
					double dy=(hookRight.posY-player.posY)*a;
					double dz=(hookRight.posZ-player.posZ)*a;
					Vec3 p=world.getWorldVec3Pool().getVecFromPool(player.posX, player.posY, player.posZ);
					Vec3 np=p.addVector(dx, dy, dz);
					if(world.rayTraceBlocks(p, np, false)==null) player.setPosition(np.xCoord, np.yCoord, np.zCoord);
					energyUpdate=true;
				}
			}
			if(player.onGround) flying=false;
			if(flying&&!energyUpdate&&(hookLeft==null||hookLeft.isDead)&&(hookRight==null||hookRight.isDead))
			{
				if(flyingCount==0)
				{
					flyingMotionY=player.motionY;
					prevEnergy=energy=player.motionX*player.motionX+player.motionZ*player.motionZ;
				}
				else if(flyingCount<FLYING_MAX&&!player.capabilities.isFlying)
				{
					player.motionY=flyingMotionY;
			        double e=Math.sqrt(energy)/Math.sqrt(player.motionX*player.motionX+player.motionZ*player.motionZ);
			        if(!Double.isNaN(e)&&!Double.isInfinite(e))
			        {
				        player.motionX*=e;
				        player.motionZ*=e;
			        }
				}
				else if(flyingCount==FLYING_MAX)
				{
			        double e=Math.sqrt(energy)/Math.sqrt(player.motionX*player.motionX+player.motionZ*player.motionZ);
			        if(!Double.isNaN(e)&&!Double.isInfinite(e))
			        {
				        player.motionX*=e;
				        player.motionZ*=e;
			        }
					energyUpdate=true;
				}
				if(flyingCount<=FLYING_MAX)
				{
					flyingCount++;
					int fc=(int)(Math.atan2(player.motionY, Math.sqrt(player.motionX*player.motionX+player.motionZ*player.motionZ))/Math.PI/2*FLYING_MAX);
					if(flyingCount<fc) flyingCount=fc;
				}
			}
			else flyingCount=0;
			if(flyingCount>FLYING_MAX||flyingCount==0)
			{
				
				double ke=player.motionX*player.motionX+player.motionY*player.motionY+player.motionZ*player.motionZ;
				double pe=GRAVITY_ACCEL*player.posY;
				if(player.onGround) energy=ke+pe;
				else if(!energyUpdate)
				{
			        double e=Math.sqrt(energy-pe)/Math.sqrt(ke);
			        if(!Double.isNaN(e)&&!Double.isInfinite(e))
			        {
				        player.motionX*=e;
				        player.motionY*=e;
				        player.motionZ*=e;
			        }
				}
			}
		}
		double b=MAX_VELOCITY/Math.sqrt(player.motionX*player.motionX+player.motionY*player.motionY+player.motionZ*player.motionZ);
		if(b<1.0&&!Double.isNaN(b)&&!Double.isInfinite(b))
		{
			player.motionX*=b;
			player.motionY*=b;
			player.motionZ*=b;
			energy=GRAVITY_ACCEL*player.posY+MAX_VELOCITY*MAX_VELOCITY;
		}
		if(player.posY>500) energy=0.0;
		else energy-=0.0001;
        if(energy<0.0||Double.isNaN(energy)||Double.isInfinite(energy)) energy=0.0;
		if(prevEnergy<energy) energy=prevEnergy;
        prevEnergy=energy;
	}
	
	@SideOnly(Side.CLIENT)
	@Override
    public ModelBiped getArmorModel(EntityLivingBase entityLiving, ItemStack itemStack, int armorSlot)
    {
        return TDMGClientProxy.modelGear;
    }
}
